import requests
import sys
import numpy as np

import numpy.matlib
import matplotlib.pyplot as plt
from numpy import linalg as la
from sklearn.externals import joblib
from sklearn.model_selection import train_test_split
from sklearn import svm
import math
import random
import util.math.rickMath as RM

import data.dataAPI.Sina as RD
import util.statistics.rickyTest as RT
import util.IO.rickyIO as RI
import util.IO.rickFile as RF

import util.deal.Strategy as Rst
def dataToXY(data,gap,reduceRate,roseColumn):
    '''
    data要求：全为float
    :param data:
    :return:
    '''

    X,Y=setXYOFfinance(data,gap,roseColumn=roseColumn)
#    Xred=reduceDim(X,exRate=reduceRate)
    Xred=X
    dim=Xred[0].__len__()
    Xnor=normalize(Xred,0,dim,gap)
    return Xnor,Y

def setXYOFfinance(data,gap,roseColumn):
    '''
    建立解释变量和预报变量
    :param data: 某个期货品种的日交易数据
    :param gap: 可调参数(通过前k天滚动窗口进行预测)
    :param dim: 数据维度
    :return: 全是float，便于后续数学运算，返回data的每行最后一个参数是预报变量
    '''
    #样本容量（通常以天为单位）
    length=data.__len__()
    #初始行情维度
    dim=data[0].__len__()

    #返回值——解释变量X(二维数组)和预报变量Y(一维数组)
    X=[]
    Y=[]
    for i in range(0,length-gap-1):
        setLine=[]
        #滚动窗口
#        setLine.append(gap)
        for j in range(i,i+gap):
            #前k天的天数k（前1天则为-1，以此类推）
            #setLine.append(j-i-gap)
            #1即为把表示日期的序列去掉
            for d in range(dim):
                #前k天的行情数据
                setLine.append(data[j][d])
        X.append(setLine)
        #设置标签
        rose = float(data[i + gap+1][roseColumn])
        if rose <= 0:
            Y.append(0)
        else:
            Y.append(1)
    return X,Y
#先主成分分析后正则化
def reduceDim(Xmatrix,exRate=0.99):
    '''
    :param Xmatrix: 解释变量矩阵：第k行为第k个样本的dim个变量
    :param dim: 变量原始维度
    :param exRate:降维后变量应该能解释exRate的降维前变量，通常为0.99，0.95,
    :return:降维后的Xmatrix', 与Xmatrix格式相同
    '''
    dim=Xmatrix[0].__len__()
    X=numpy.mat(Xmatrix)
    Xt=X.transpose()
    cov=Xt*X/dim
    matrix=numpy.mat(cov)
    U,sigma,V=la.svd(matrix)
    sigmaSum=0
    k=dim
    print("降维前的解释变量个数k(包括截距):",k)
    for i in range(dim):
        sigmaSum+=sigma[i]
    for i in range(1,dim+1):
        subSum=0
        for j in range(i):
            subSum+=sigma[j]
        rate=subSum/sigmaSum
        if rate>=exRate:
            k=i
            break
    print("降维后的解释变量个数k(包括截距):",k)
    answer = Xmatrix
    if k!=dim:
        print("success to reduce dimensionality!")
        Ureduce=U[:,:k]
        Z=X*Ureduce
        answer=Z.tolist()
    else:
        print("fail to reduce dimensionality!")
        print("the exRate is to large")
#是否加截距
#    for i in range(answer.__len__()):
#        answer[i].append(1)
    return answer
def normalize(data,start,end,gap):
    '''
    数据归一化
    :param data:
    :return: 包含日期、日收盘价、日成交量
    '''
    small=[]
    big=[]
    all=[]
    for i in range(start,end):
        small.append(float(data[0][i]))
        big.append(float(data[0][i]))
        all.append(0)
    n=data.__len__()
    for i in data:
        for j in range(start,end):
            i[j]=float(i[j])
        for j in range(start,end):
            if i[j]<small[j-start]:
                small[j-start]=i[j]
            if i[j]>big[j-start]:
                big[j-start]=i[j]
            all[j-start]+=i[j]
    for i in range(end-start):
        all[i]=all[i]/n
        big[i]=big[i]-small[i]

    answer=[]
    for i in range(data.__len__()):
        line=[]
        for j in range(start,end):
            if big[j-start]==0:
                line.append(data[i][j]/gap+0.5)
            else:
                line.append((data[i][j]-all[j-start])/big[j-start])
        answer.append(line+data[i][end:])
    return answer
#自定义SVM
def GaussKernel(x,l,sigma):
    sum=0
    n=x.__len__()
    for i in range(n):
        sum+=(x[i]-l[i])**2
    return math.exp(-sum/(2*sigma**2))
def cost1(theta,x):
    pro=RM.vectorProduct(theta,x)
    if pro>=1:
        return 0
    else:
        return -pro+1
def cost0(theta,x):
    pro=RM.vectorProduct(theta,x)
    if pro<=-1:
        return 0
    else:
        return pro+1
def JofSVM(theta,X,Y,C):
    '''
    代价函数
    :param theta:
    :param data: float！！
    :return:
    '''
    answer = 0
    len = X.__len__()
    for i in range(len):
        add=1
        if Y[i]==1:
            add*=cost1(theta,X[i])
        else:
            add*=cost0(theta,X[i])
        answer += add
    answer=answer*C
    answer+=RM.vectorProduct(theta,theta)/2
    return answer
def gradientDescent(C,sigma,theta,X,Y,alpha,times):
    '''
    梯度下降算法，核心！
    :param theta:
    :param data:
    :param alpha:
    :param times:
    :return:
    '''
    xTime=[]
    jValue=[]
    for time in range(times):
        xTime.append(time)
        thetaNext=theta.copy()
        len=theta.__len__()
        for j in range(len):
            sub = 0
            for ii in range(X.__len__()):
                product=RM.vectorProduct(X[ii], theta)
                print(ii,X.__len__(),Y.__len__())
                if product<=-1:
                    sub+=-Y[ii]*X[ii][j]
                elif product>=1:
                    sub+=(1-Y[ii])*X[ii][j]
                else:
                    sub+=(1-2*Y[ii])*X[ii][j]
            sub=sub+theta[j]
            sub=sub*alpha
            thetaNext[j]=thetaNext[j]-sub
        theta=thetaNext
        jValue.append(JofSVM(theta[:],X[:],Y[:],C))
        print('\r' +"正在梯度下降:"+ str((time+1)*100/times), end='%', flush=True)
    print("\n"+"梯度下降完成")
    print("学习曲线如图所示:")
    plt.plot(xTime,jValue)
    plt.show()
    return theta



def Score(x,y,Xc=100,Xgamma=20,modelName='model2'):
    x_train,x_test,y_train,y_test=train_test_split(x, y, train_size=0.8)
    #C越大，gamma越大，过拟合
    clf=svm.SVC(C=Xc,kernel='rbf',gamma=Xgamma,decision_function_shape='ovo',random_state=1)
    clf.fit(x_train,y_train)
    joblib.dump(clf, modelName)
    print("Done\n")
    model1 = joblib.load(modelName)
    score1=model1.score(x_test,y_test)
    print("score:",score1,Xc,Xgamma)
    y_hat =model1.predict(x_test)
    print(y_hat)

    # 检测SVM正确性

    return score1
def predict(modelSrc,X):
    model = joblib.load(modelSrc)
    y_hat=model.predict(X)
    return y_hat

if __name__=='__main__':

    src = "D:\大二下\数据科学\带作业\SVM\\"
    Xpath = src + 'Xnor.csv'
    Ypath = src + 'Y.csv'
    X = RF.read(Xpath)
    Y = RF.read(Ypath, dim=1)
    y=predict('model2',X[664:])
    print(Y[664:])
    print(y)
    print(RT.getFScore(Y[664:],y))
    '''
    
    


    c = list(zip(X, Y))
    random.shuffle(c)
    X[:], Y[:] = zip(*c)
    RF.write(Xpath,X)
    RF.write(Ypath,Y,dim=1)

    
    Score(X[:664], Y[:664], 100, 0.1)
    '''


    '''
    src = "C:\\Users\\29390\\Desktop\\牧羊人\\项目\\Buffet2\\SVM\\RB10\\dispose6\\"
    Xpath = src + 'Xnor.csv'
    Ypath = src + 'Y.csv'
    X = RF.read(Xpath)
    Y = RF.read(Ypath, dim=1)
#    Score(X[:1913], Y[:1913], 100, 0.1)
    model1 = joblib.load("train1_model.m")
    y_hat=model1.predict(X[1913:2115])
    print(y_hat)
    score1=model1.score(X[1913:2115],Y[1913:2115])
    print(score1)
    RF.write('yhat.csv',y_hat,dim=1)
    '''
